//NOTE: check Key % pattern[X01] or not ???? 
// take key as string, now!  uncheck the pattern [X00]
// if want check the key , see json impl: MapKeySerializer

use crate::error::{Result, Error};
use crate::formatter::{Formatter, CompactFormatter};
use crate::curly_bracket_map_flag::CurlyBracketMapFlag;

use std::io;
use std::num::FpCategory;

use serde::ser::{self, Impossible};

pub struct Serializer<W, F= CompactFormatter> {
    writer: W,
    formatter: F
}


impl <W, F> Serializer<W, F> 
where 
    W: io::Write ,
    F: Formatter,
{
    pub fn with_formatter(writer: W, formatter: F) -> Self {
        Self { writer, formatter }
    }
}


impl<'a, W, F> ser::Serializer for &'a mut Serializer<W, F> 
where  W: io::Write,
       F: Formatter,
{
    type Ok = ();
    type Error = Error;

    type SerializeSeq = Map<'a, W, F>;
    type SerializeTuple = Map<'a, W, F>;
    type SerializeMap = Map<'a, W, F>;
    type SerializeStruct = Map<'a, W, F>;

    type SerializeTupleStruct = Impossible<Self::Ok, Self::Error>;
    type SerializeTupleVariant = Impossible<Self::Ok, Self::Error>;
    type SerializeStructVariant = Impossible<Self::Ok, Self::Error>;

    #[inline]
    fn serialize_bool(self, v: bool) -> Result<Self::Ok> {
        self.formatter
            .write_bool(&mut self.writer, v)
            .map_err(Error::io)
    }

    #[inline]
    fn serialize_i8(self, v: i8) -> Result<Self::Ok> {
        self.formatter
            .write_i8(&mut self.writer, v)
            .map_err(Error::io)
    }
    #[inline]
    fn serialize_i16(self, v: i16) -> Result<Self::Ok> {
        self.formatter
            .write_i16(&mut self.writer, v)
            .map_err(Error::io)
    }
    #[inline]
    fn serialize_i32(self, v: i32) -> Result<Self::Ok> 
    {
        self.formatter
            .write_i32(&mut self.writer, v)
            .map_err(Error::io)
    }
    #[inline]
    fn serialize_i64(self, v: i64) -> Result<Self::Ok> 
    {
        self.formatter
            .write_i64(&mut self.writer, v)
            .map_err(Error::io)
    }
    #[inline]
    fn serialize_i128(self, v: i128) -> Result<Self::Ok> 
    {
        self.formatter
            .write_i128(&mut self.writer, v)
            .map_err(Error::io)
    }

    #[inline]
    fn serialize_u8(self, v: u8) -> Result<Self::Ok> {
        self.formatter
            .write_u8(&mut self.writer, v)
            .map_err(Error::io)
    }
    #[inline]
    fn serialize_u16(self, v: u16) -> Result<Self::Ok> {
        self.formatter
            .write_u16(&mut self.writer, v)
            .map_err(Error::io)
    }
    #[inline]
    fn serialize_u32(self, v: u32) -> Result<Self::Ok> 
    {
        self.formatter
            .write_u32(&mut self.writer, v)
            .map_err(Error::io)
    }
    #[inline]
    fn serialize_u64(self, v: u64) -> Result<Self::Ok> 
    {
        self.formatter
            .write_u64(&mut self.writer, v)
            .map_err(Error::io)
    }
    #[inline]
    fn serialize_u128(self, v: u128) -> Result<Self::Ok> 
    {
        self.formatter
            .write_u128(&mut self.writer, v)
            .map_err(Error::io)
    }
    #[inline]
    fn serialize_f32(self, v: f32) -> Result<Self::Ok> 
    {
        match v.classify() {
            FpCategory::Nan | FpCategory::Infinite => 
                self.formatter
                    .write_null(&mut self.writer)
                    .map_err(Error::io),
            _ => 
                self.formatter  
                    .write_f32(&mut self.writer, v)
                    .map_err(Error::io),
        }
    }
    #[inline]
    fn serialize_f64(self, v: f64) -> Result<Self::Ok> 
    {
        match v.classify() {
            FpCategory::Nan | FpCategory::Infinite => 
                self.formatter
                    .write_null(&mut self.writer)
                    .map_err(Error::io),
            _ => 
                self.formatter  
                    .write_f64(&mut self.writer, v)
                    .map_err(Error::io),
        }
    }

    #[inline]
    fn serialize_none(self) -> Result<Self::Ok> {
        self.serialize_unit()
    }
    #[inline]
    fn serialize_some<T>(self, v: &T) -> Result<()>
    where
        T: ?Sized + ser::Serialize,
    {
        v.serialize(self)
    }
    #[inline]
    fn serialize_unit(self) -> Result<Self::Ok> {
        self.formatter
            .write_null(&mut self.writer)
            .map_err(Error::io)
    }
    #[inline]
    //struct Name or PhantomData<T> 
    fn serialize_unit_struct(self, _name: &'static str) -> Result<Self::Ok> {
        Err(Error::unimplemented("tuple_struct: struct Meter; not-support in gtp"))
    }
    #[inline]
    fn serialize_bytes(self, v: &[u8]) -> Result<Self::Ok> {
        self.formatter
            .write_byte_array(&mut self.writer, v)
            .map_err(Error::io)
    }
    #[inline]
    fn serialize_char(self, v: char) -> Result<Self::Ok> {
        let mut buf = [0; 4];
        self.serialize_str(v.encode_utf8(&mut buf))
    } 
    #[inline]
    fn serialize_str(self, v: &str) -> Result<Self::Ok> {
        self.formatter
            .write_escaped_str(&mut self.writer, v)
            .map_err(Error::io)
    }

    #[inline]
    // enum E {A};
    fn serialize_unit_variant( self, _name: &'static str, _variant_index: u32, variant: &'static str) -> Result<Self::Ok> {
        self.serialize_str(variant)
    }

    #[inline]
    fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq> {
        if len != Some(0_usize) {
            self.formatter
                .begin_array(&mut self.writer)
                .map_err(Error::io)?;
            Ok(Map::new (self, State::First))
        } else {
            Ok(Map::new(self, State::Empty))
        }
    }
    #[inline]
    // (u8, String)
    fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple> {
        self.serialize_seq(Some(len))
    }

    #[inline]
    fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap> {
        if CurlyBracketMapFlag::real_len(len) != 0_usize { // len != 0
            if CurlyBracketMapFlag::has_curly_bracket(len) {
                self.formatter
                .begin_object(&mut self.writer)
                .map_err(Error::io)?;

                Ok(Map::new(self, State::First))
            } else {
                Ok(Map::new_without_curly_brackets(self, State::First))
            }
        } else { // real_len == 0
            Ok(Map::new(self, State::Empty))
        }
    }
    #[inline]
    // using: v::seriaize() : 
    // -> let state = ser.serialize_struct("Test", 4);
    // -> state.serialize_field(key, value)
    // -> state.end();
    fn serialize_struct(self, _name: &'static str, len: usize) -> Result<Self::SerializeStruct> {
        if len == 0 {
            Ok(Map::new(self, State::Empty))
        } else {
            Ok(Map::new(self, State::First,))
        }
    }


    #[inline]
    //struct Milliemters(u32);
    fn serialize_newtype_struct<T>(self, _name: &'static str, _v: &T) 
        -> Result<Self::Ok>
    where
        T: ?Sized + ser::Serialize,
    {
        Err(Error::unimplemented("tuple_struct: struct Meter(u32) not-support in gtp"))
    }
    #[inline]
    //enum E { A(u8), B(u8), C(u8) }; for each C
    fn serialize_newtype_variant<T>(self, _name: &'static str, _variant_index: u32, _variant: &'static str, _v:& T,) 
        -> Result<Self::Ok>
    where 
        T: ?Sized + ser::Serialize 
    {
        Err(Error::unimplemented("newtype_varaint: enum E{ A(u8), B(u8), C(u8)} not-support in gtp"))
    }

    #[inline]
    //struct name(u8, u8, u8)
    fn serialize_tuple_struct(self, _name: &'static str, _len: usize,) 
        -> Result<Self::SerializeTupleStruct> 
    {
        Err(Error::unimplemented("tuple_struct: struct name(u8, u8, u8) not-support in gtp"))
    }
    #[inline]
    // enum E { A(u8, u8, u8){
    fn serialize_tuple_variant(self, _name: &'static str, _variant_index: u32, _variant: &'static str, _len: usize,) 
        -> Result<Self::SerializeTupleVariant> 
    {
        Err(Error::unimplemented("tuple_variant: enum E { A(u8, u8, u8)} not-support in gtp"))
    }
    #[inline]
    //enum E{ A{C,D,B}}
    fn serialize_struct_variant(self, _name: &'static str, _variant_index: u32, _variant: &'static str, _len: usize,)
        -> Result<Self::SerializeStructVariant> 
    {
        Err(Error::unimplemented("tuple_variant: enum E { A{I, II, III}} not-support in gtp"))

    }
}

#[derive(Eq, PartialEq)]
pub enum State {
    Empty,
    First,
    Rest,
}

pub struct Map<'a, W: 'a , F: 'a> {
    ser: &'a mut Serializer<W, F>,
    state: State,
    // has_curly_brackets = true =>  origin map begining with "{}"
    // has_curly_brackets = false => map begining without "{}
    has_curly_brackets: bool,
}

impl<'a, W, F> Map<'a, W, F> 
where W: 'a, F: 'a,
{
    fn new(ser: &'a mut Serializer<W, F>, state: State) -> Self{
        Self { 
            ser, 
            state,
            has_curly_brackets: true
        }
    }
    fn new_without_curly_brackets(ser: &'a mut Serializer<W, F>, state: State) -> Self{
        Self { 
            ser, 
            state,
            has_curly_brackets : false
        }
    }
}


impl<'a, W, F> ser::SerializeSeq for Map<'a, W, F> 
where W: io::Write,
      F: Formatter,
{
    type Ok = ();
    type Error = Error;

    #[inline]
    fn serialize_element<T>(&mut self, v: &T) -> Result<Self::Ok> 
    where 
        T: ?Sized + ser::Serialize, 
    {
        self.ser
            .formatter
            .begin_array_value(&mut self.ser.writer, self.state == State::First)
            .map_err(Error::io)?;
        self.state = State::Rest;

        v.serialize(&mut *(self.ser))?;

        self.ser
            .formatter
            .end_array_value(&mut self.ser.writer)
            .map_err(Error::io)
    }
    #[inline]
    fn end(self) -> Result<Self::Ok> {
        match self.state {
            State:: Empty => Ok(()),
            _ => self.ser   
                    .formatter
                    .end_array(&mut self.ser.writer)
                    .map_err(Error::io),
        }
    }
}

impl<'a, W, F> ser::SerializeTuple for Map<'a, W, F> 
where W: io::Write,
      F: Formatter,
{
    type Ok = ();
    type Error = Error;

    #[inline]
    fn serialize_element<T>(&mut self, v: &T) -> Result<Self::Ok> 
    where 
        T: ?Sized + ser::Serialize, 
    {
        ser::SerializeSeq::serialize_element(self, v)
    }
    #[inline]
    fn end(self) -> Result<Self::Ok> {
        ser::SerializeSeq::end(self)
    }
}


impl<'a, W, F> ser::SerializeMap for Map<'a, W, F> 
where W: io::Write,
      F: Formatter,
{
    type Ok = ();
    type Error = Error;

    #[inline]
    fn serialize_entry<K, V>( &mut self, k: &K, v: &V) -> Result<Self::Ok>
    where
        K: ?Sized + ser::Serialize,
        V: ?Sized + ser::Serialize,
    {
        match self.state {
            State::Empty => Ok(()),
            _ => {
                self.serialize_key(k)?;
                self.serialize_value(v)
            }
        }
    }
    #[inline]
    fn serialize_key<T>(&mut self, k: &T) -> Result<Self::Ok>
        where T: ser::Serialize + ?Sized
    {
        self.ser.formatter
            .begin_object_key(&mut self.ser.writer, self.state == State::First)
            .map_err(Error::io)?;
        self.state = State::Rest;

        k.serialize(&mut *self.ser)?;

        self.ser.formatter
            .end_object_key(&mut self.ser.writer)
            .map_err(Error::io)
    }
    #[inline]
    fn serialize_value<T>(&mut self, v: &T) -> Result<Self::Ok>
        where T: ser::Serialize + ?Sized
    {
        self.ser.formatter
            .begin_object_value(&mut self.ser.writer)
            .map_err(Error::io)?;

        v.serialize(&mut *self.ser)?;

        self.ser.formatter
            .end_object_value(&mut self.ser.writer)
            .map_err(Error::io)
    }
    #[inline]
    fn end(self) -> Result<Self::Ok>
    {
        match self.state {
            State::Empty => Ok(()),
            _ => { 
                if self.has_curly_brackets {
                    self.ser.formatter
                    .end_object(&mut self.ser.writer)
                    .map_err(Error::io)
                } else {
                    Ok(())
                }
            }
        }
    }
}


impl<'a, W, F> ser::SerializeStruct for Map<'a, W, F> 
where W: io::Write,
      F: Formatter,
{
    type Ok = ();
    type Error = Error;

    #[inline]
    fn serialize_field<T>(&mut self, k: &'static str, v: &T) -> Result<Self::Ok>
    where
        T: ?Sized + ser::Serialize,
    {
        match self.state {
            State::Empty => Ok(()),
            _ => ser::SerializeMap::serialize_entry(self, k, v),
        }
    }
    #[inline]
    fn end(self) -> Result<()> {
        Ok(())
    }
}






#[cfg(test)]
mod test {
    //use super::*;
    use std::collections::HashMap;
    #[test]
    fn for_primitive_type(){
        assert_eq!("1", crate::to_string(&1_u8).unwrap());

        assert_eq!("1.01", crate::to_string(&1.01_f32).unwrap());
        assert_eq!("1.012", crate::to_string(&1.012_f64).unwrap());
        assert_eq!("100.0", crate::to_string(&1e2_f32).unwrap());

        assert_eq!("string", crate::to_string("string").unwrap());
        assert_eq!("string", crate::to_string(&"string".to_string()).unwrap());

        assert_eq!("[1,2,3]", crate::to_string(&[1_u8, 2_u8, 3_u8]).unwrap());

        let mut map = HashMap::new();
        map.insert("a", "1");
        assert_eq!("{a=1}", crate::to_string(&map).unwrap());

        map.clear();
        map.insert("a", "a\\b,c=d[e]f{g}h");
        assert_eq!("{a=a\\\\b\\,c\\=d\\[e\\]f\\{g\\}h}", crate::to_string(&map).unwrap());


        map.clear();// empty map 
        assert_eq!("", crate::to_string(&map).unwrap());

        assert_eq!("", crate::to_string(&[0_i8; 0]).unwrap());
    }
    use serde::Serialize;


    #[test]
    fn for_struct() {
        #[derive(Serialize)]
        struct Test<'a> {
            int: i8,
            f:  f32,
            #[serde(skip_serializing_if = "crate::skip_ser_func::str")]
            s: String,
            #[serde(skip_serializing_if = "crate::skip_ser_func::slice")]
            a: &'a [u8],
            #[serde(skip_serializing_if = "crate::skip_ser_func::hashmap")]
            m: HashMap<String, String>,
        }
        let mut m = HashMap::<String, String>::new();
        m.insert("hello".to_string(), "world".to_string());
        let a: &[u8] = &[1_u8, 2_u8, 3_u8, 4_u8, 5_u8, 6_u8, 7_u8, 8_u8];
        let mut v = Test {
            int: 8_i8,
            f: 1.344e2,
            s: "hello world".to_string(),
            a: a,
            m: m,
        };
        {
            let expect = "int=8,f=134.4,s=hello world,a=[1,2,3,4,5,6,7,8],m={hello=world}";
            assert_eq!(expect, crate::to_string(&v).unwrap());
        }

        {// clear map in struct
            v.m.clear();
            let expect = "int=8,f=134.4,s=hello world,a=[1,2,3,4,5,6,7,8]";
            assert_eq!(expect, crate::to_string(&v).unwrap());
        }

        {//clear ref of array in struct
            let a = &[8_u8; 0];
            v.a = a;
            let expect = "int=8,f=134.4,s=hello world";
            assert_eq!(expect, crate::to_string(&v).unwrap());
        }
        {
            v.s = "".to_string();
            let expect = "int=8,f=134.4";
            assert_eq!(expect, crate::to_string(&v).unwrap());
        }
    }
}
